﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.RemoteCtrls.Services;
using DWF.Studio.RemoteCtrls.SnippetExplorer.Node;
using DWF.Studio.Share.Utils;
using System;
using System.Activities;
using System.Activities.Presentation;
using System.Activities.Validation;
using System.Activities.XamlIntegration;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;

namespace DWF.Studio.RemoteCtrls.SnippetExplorer
{
    /// <summary>
    /// UCtrlSnippetExplorer.xaml 的交互逻辑
    /// </summary>
    public partial class UCtrlSnippetExplorer : UserControl
    {
        private ObservableCollection<SnippetNode> _nodeCollection = new ObservableCollection<SnippetNode>();

        private SnippetManager _snippetManager = null;

        /// <summary>
        /// 片段模型改变
        /// </summary>
        public Action<ShowSnippetEventArgs> SnippetShow = null;
        /// <summary>
        /// 修复片段依赖活动包
        /// </summary>
        public Action<RepairSnippetEventArgs> RepairSnippetActivity = null;
        /// <summary>
        /// 片段覆盖提示
        /// </summary>
        public Action<SnippetCoverEventArgs> IsCoverSnippet = null;

        /// <summary>
        /// 片段缺少依赖活动
        /// </summary>
        public Action<EventArgs> CheckSnippetActivity = null;

        public UCtrlSnippetExplorer()
        {
            InitializeComponent();

            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                init();
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void init()
        {
            _snippetManager = new SnippetManager();

            var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets");//片段安装路径
            var snippetNodeCache = _snippetManager.LoadSnippets(path);

            _nodeCollection.Clear();
            snippetNodeCache.ToList().ForEach(p => _nodeCollection.Add(p));
            this.tvSnippets.ItemsSource = _nodeCollection;
            btnExpand.ToolTip = LocalizationProvider.GetLocalizedString("UCtrlProjectExplorer_Top_Button_AllExpand");
            btnCollapse.ToolTip = LocalizationProvider.GetLocalizedString("UCtrlProjectExplorer_Top_Button_AllCollapse");
        }
        /// <summary>
        /// 保存片段以后重新加载
        /// </summary>
        public void Reload()
        {
            _snippetManager = new SnippetManager();

            var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets");//片段安装路径
            var snippetNodeCache = _snippetManager.LoadSnippets(path);

            _nodeCollection.Clear();
            snippetNodeCache.ToList().ForEach(p => _nodeCollection.Add(p));
            this.tvSnippets.ItemsSource = _nodeCollection;
        }
        /// <summary>
        /// 双击片段树节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TvItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var tvItem = sender as TreeViewItem;
            if (tvItem != null)
            {
                var snippetFile = tvItem.DataContext as SnippetFile;
                if (snippetFile != null)
                {
                    SnippetShow?.Invoke(new ShowSnippetEventArgs(snippetFile.FullName));
                }
            }
        }

        private void TvItem_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                var snippetFile = this.tvSnippets.SelectedItem as SnippetFile;
                if (snippetFile != null)
                {
                    SnippetTemplateFactory.SnippetFullName = snippetFile.FullName;
                    var validate = this.Validate(snippetFile.FullName);
                    if (validate.Count() > 0)
                    {
                        CheckSnippetActivity?.Invoke(EventArgs.Empty);
                    }

                    IDataObject dataObject = new DataObject();
                    dataObject.SetData(DragDropHelper.WorkflowItemTypeNameFormat, typeof(SnippetTemplateFactory).AssemblyQualifiedName);
                    DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Copy | DragDropEffects.Link);
                }
            }
        }
        
        /// <summary>
        /// 搜索框查询
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SearchSnippet_OnSearch(object sender, SearchSnippetEventArgs e)
        {
            var txt = e.SearchSnippetText;
            if (!String.IsNullOrWhiteSpace(txt))
            {
                searchSnippetNodesRecursion(txt, _nodeCollection);
            }
            else
            {
                searchSnippetNodesRecursion(String.Empty, _nodeCollection);
            }
        }

        /// <summary>
        /// 搜索树创建
        /// </summary>
        /// <param name="txt"></param>
        /// <param name="currentNodes"></param>
        private void searchSnippetNodesRecursion(string txt, ObservableCollection<SnippetNode> currentNodes)
        {
            foreach (var node in currentNodes)
            {
                if (node.IsLeaf)
                {
                    node.Visible = node.DisplayName.ToLower().Contains(txt.ToLower());
                }
                else
                {
                    searchSnippetNodesRecursion(txt, node.Children);
                    node.Visible = node.Children.Any(item => item.Visible);
                }
            }
        }

        private void btnExpand_Click(object sender, RoutedEventArgs e)
        {
            expandNodesRecursion(_nodeCollection);
        }

        private void btnCollapse_Click(object sender, RoutedEventArgs e)
        {
            collapseNodesRecursion(_nodeCollection);
        }

        private void expandNodesRecursion(ObservableCollection<SnippetNode> currentNodes)
        {
            foreach (var node in currentNodes)
            {
                if (node is SnippetFolder)
                {
                    node.IsExpanded = true;
                    expandNodesRecursion(node.Children);
                }
            }
        }

        private void collapseNodesRecursion(ObservableCollection<SnippetNode> currentNodes)
        {
            foreach (var node in currentNodes)
            {
                if (node is SnippetFolder)
                {
                    node.IsExpanded = false;
                    collapseNodesRecursion(node.Children);
                }
            }
        }
        /// <summary>
        /// 右键引入
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvSnippets_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            var tvItem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
            if (tvItem != null)
            {
                if (tvItem.DataContext != null)
                {
                    if (tvItem.DataContext is SnippetFolder)
                    {
                        var folder = tvItem.DataContext as SnippetFolder;
                        if (folder.Name != "Favorites")
                            return;
                        var menuItemAdd = new MenuItem();
                        menuItemAdd.Name = "addFavorite";
                        menuItemAdd.Header = LocalizationProvider.GetLocalizedString("UCtrlSnippetExplorer_ContextMenu_MenuItem_AddSnippet");
                    }
                    else if (tvItem.DataContext is SnippetFile)
                    {
                        SnippetNode node = tvItem.DataContext as SnippetNode;

                        var menuItemAdd = LogicalTreeHelper.FindLogicalNode(tvItem.ContextMenu, "itemAddFavorite") as MenuItem;
                        var menuItemRemove = LogicalTreeHelper.FindLogicalNode(tvItem.ContextMenu, "itemRemoveFavorite") as MenuItem;
                        var menuItemCheck = LogicalTreeHelper.FindLogicalNode(tvItem.ContextMenu, "itemCheckSnippet") as MenuItem;
                        if (menuItemAdd != null && menuItemRemove != null)
                        {
                            menuItemAdd.Header = LocalizationProvider.GetLocalizedString("UCtrlSnippetExplorer_ContextMenu_MenuItem_AddSnippet");
                            menuItemAdd.Icon = new System.Windows.Controls.Image
                            {
                                Source = new BitmapImage(new Uri("/DWF.Studio;component/Resources/SnippetAndActivity/AddSnippet.png", UriKind.Relative))
                            };
                            menuItemRemove.Header = LocalizationProvider.GetLocalizedString("UCtrlSnippetExplorer_ContextMenu_MenuItem_RemoveSnippet");
                            menuItemRemove.Icon = new System.Windows.Controls.Image
                            {
                                Source = new BitmapImage(new Uri("/DWF.Studio;component/Resources/SnippetAndActivity/RemoveSnippet.png", UriKind.Relative))
                            };
                            menuItemCheck.Header = LocalizationProvider.GetLocalizedString("UCtrlSnippetExplorer_ContextMenu_MenuItem_RepairSnippet");
                            menuItemCheck.Icon = new System.Windows.Controls.Image
                            {
                                Source = new BitmapImage(new Uri("/DWF.Studio;component/Resources/SnippetAndActivity/CheckSnippet.png", UriKind.Relative))
                            };
                        }
                        if (node != null)
                        {
                            var targetFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets\\Favorites\\");
                            var folderName = node.FullName.Replace(node.Name, "");
                            if (folderName != targetFolder)
                            {
                                if (menuItemAdd != null)
                                {
                                    menuItemAdd.IsEnabled = true;
                                    menuItemRemove.IsEnabled = false;
                                    menuItemCheck.IsEnabled = false;
                                }
                            }
                            else
                            {
                                if (menuItemAdd != null)
                                {
                                    menuItemAdd.IsEnabled = true;
                                    menuItemRemove.IsEnabled = true;
                                    menuItemCheck.IsEnabled = true;
                                }
                            }
                        }
                    }
                }

                tvItem.Focus();
                e.Handled = true;
            }
        }
        /// <summary>
        /// 添加收藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_AddFavorite(object sender, RoutedEventArgs e)
        {
            var menuItem = VisualUpwardSearch<MenuItem>(e.OriginalSource as DependencyObject) as MenuItem;
            var targetFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets\\Favorites");
            
            System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)//注意，此处一定要手动引入System.Window.Forms空间，否则你如果使用默认的DialogResult会发现没有OK属性
            {
                var fullName= openFileDialog.FileName;
                var fileName = openFileDialog.SafeFileName;
                if (System.IO.Path.GetExtension(fileName) != ".xaml")
                {
                    return;
                }
                if (!FileHelper.CheckFolderExisting(targetFolder))
                {
                    FileHelper.CreateFolder(targetFolder);
                }
                if (FileHelper.CheckFileExisting(System.IO.Path.Combine(targetFolder, fileName)))//发现有同名文件，向主域发出提示
                {
                    IsCoverSnippet?.Invoke(new SnippetCoverEventArgs(fileName,fullName,targetFolder));
                }
                else
                { 
                    FileHelper.CopyFileToFolder(fullName, targetFolder);
                }
            }
            Reload();
        }
        public void AddFavorite(string fullName,string targetFolder)
        {
            FileHelper.CopyFileToFolder(fullName, targetFolder);
        }
        /// <summary>
        /// 删除收藏
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_RemoveFavorite(object sender, RoutedEventArgs e)
        {
            var menuItem = VisualUpwardSearch<MenuItem>(e.OriginalSource as DependencyObject) as MenuItem;
            if (menuItem != null)
            {
                var snippetNode = menuItem.DataContext as SnippetNode;
                if (snippetNode != null)
                {
                    var targetFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets\\Favorites");
                    var filePath = System.IO.Path.Combine(targetFolder, snippetNode.Name);
                    FileHelper.DeleteFile(filePath);
                }
                Reload();
            }
        }
        /// <summary>
        /// 尝试修复片段
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItem_CheckSnippet(object sender, RoutedEventArgs e)
        {
            var menuItem = VisualUpwardSearch<MenuItem>(e.OriginalSource as DependencyObject) as MenuItem;
            if (menuItem != null)
            {
                var snippetNode = menuItem.DataContext as SnippetNode;
                if (snippetNode != null)
                {
                    var targetFolder = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "snippets\\Favorites");
                    var filePath = System.IO.Path.Combine(targetFolder, snippetNode.Name);
                    RepairSnippetActivity?.Invoke(new RepairSnippetEventArgs(filePath));
                }
                //Reload();
            }
        }
        /// <summary>
        /// 校验脚本
        /// </summary>
        /// <param name="workflowDesigner"></param>
        /// <returns></returns>
        private IEnumerable<ValidationInfo> Validate(string snippetFullPath)
        {
            WorkflowDesigner wf = new WorkflowDesigner();
            wf.Load(snippetFullPath);
            List<ValidationInfo> infos = new List<ValidationInfo>();
            try
            {
                Activity root = ActivityXamlServices.Load(new StringReader(wf.Text));
                ValidationResults results = ActivityValidationServices.Validate(root);

                foreach (var error in results.Errors)
                {
                    infos.Add(new ValidationInfo(error));
                }

                foreach (var warning in results.Warnings)
                {
                    infos.Add(new ValidationInfo(warning));
                }
            }
            catch (Exception ex)
            {
                infos.Add(new ValidationInfo(ex));
            }

            return infos;
        }
        /// <summary>
        /// 返回约定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
        {
            while (source != null && source.GetType() != typeof(T))
                source = VisualTreeHelper.GetParent(source);

            return source;
        }
    }
    public class TreeViewItemHelper
    {
        public static bool GetShowBackground(DependencyObject obj)
        {
            return (bool)obj.GetValue(ShowBackgroundProperty);
        }

        public static void SetShowBackground(DependencyObject obj, bool value)
        {
            obj.SetValue(ShowBackgroundProperty, value);
        }
        public static readonly DependencyProperty ShowBackgroundProperty = DependencyProperty.RegisterAttached(
            "ShowBackground",
            typeof(bool),
            typeof(TreeViewItemHelper),
            new PropertyMetadata(OnShowBackground)
        );

        private static void OnShowBackground(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var item = d as TreeViewItem;
            if (item == null)
                return;
            var node = item.DataContext as SnippetFile;
            if (node == null)
            {
                item.Background = new SolidColorBrush(Colors.Transparent);
                return;
            }
        }
    }
}
